﻿using Peak.Can.Basic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Channels;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace 项目模板2.Communication
{
    using TPCANHandle = System.UInt16;


    public enum DeviceProtocol
    {
        DEVICE_MODE_NONE = 0,
        DEVICE_MODE_BASIC ,
        DEVICE_MODE_UDS_DTC,
        DEVICE_MODE_UDS_BOOT,
        DEVICE_MODE_CCP,
    }

    public class DeviceM
    {



        #region 通信参数
            public TPCANBaudrate Baud { get; set; }

            public TPCANHandle UsbChl { get; set; }

        #endregion


        #region 连接、断开事件
        public delegate void DeviceConnectDelegate();
        public delegate void RecvDelegate(TPCANMsg CANMsg);

        public event DeviceConnectDelegate ConnectEvent;
        public event DeviceConnectDelegate DisonnectEvent;
        public event RecvDelegate RecvEvent;
        #endregion
        public DeviceProtocol Protocol { get; set; }

        public bool ConnetcState { get; set; }
        public bool InitState { get; set; }
        Thread ReceiveThread;


        public string InitErrMessage { get; set; }


        public bool InitDevice(TPCANBaudrate baud,TPCANHandle ch, DeviceProtocol prot,out string errStr) 
        {
            errStr = null;
            Baud = baud;
            UsbChl = ch;
            Protocol = prot;
            if (Protocol == DeviceProtocol.DEVICE_MODE_BASIC)
            {
                TPCANStatus ret = TPCANStatus.PCAN_ERROR_OK;
                ret = PCANBasic.Initialize(UsbChl, Baud);
                if (ret != TPCANStatus.PCAN_ERROR_OK)
                {
                    InitState = false;
                    errStr = ret.ToString();
                }
                else
                {
                    InitState = true;
           
                }
                InitErrMessage = ret.ToString();


            }

           
            return InitState;


        }

        public void Open() 
        {
            if (!InitState)
                return;
            if (Protocol == DeviceProtocol.DEVICE_MODE_BASIC)
            {
                ReceiveThread = new Thread(new ThreadStart(ReceiveFrameThread));
                ReceiveThread.Start();
                ConnectEvent?.Invoke();
                ConnetcState = true;
            }

            else if (Protocol == DeviceProtocol.DEVICE_MODE_UDS_BOOT)
            {
                ConnectEvent?.Invoke();
                ConnetcState = true;
            }
        }

        private void ReceiveFrameThread()
        {
            while (true)
            {

                TPCANStatus ret = PCANBasic.Read(UsbChl, out TPCANMsg CANMsg, out TPCANTimestamp CANTimeStamp);


                if (ret == TPCANStatus.PCAN_ERROR_OK) //已接收到数据
                {
                    RecvEvent?.Invoke(CANMsg);
                }

                
                Thread.Sleep(1);
            }
        }

        public void Close() 
        {
            if (Protocol == DeviceProtocol.DEVICE_MODE_BASIC)
            {
                if (ConnetcState)
                {
                    ReceiveThread.Abort();
                }

                DisonnectEvent?.Invoke();
                PCANBasic.Uninitialize(UsbChl);
                ConnetcState = false;
                InitState = false;

            }
          

        }

        public TPCANStatus Write(byte[] frame, byte len, uint Id)
        {
            TPCANStatus ret = TPCANStatus.PCAN_ERROR_OK;
            if (!ConnetcState) 
                return TPCANStatus.PCAN_ERROR_BUSOFF;
            if (Protocol == DeviceProtocol.DEVICE_MODE_BASIC)
            {
                TPCANMsg txBuf = new TPCANMsg();
                txBuf.LEN = len;
                txBuf.ID = Id;
                txBuf.DATA = frame;
                if (Id > 0x7ff)
                {
                    txBuf.MSGTYPE = TPCANMessageType.PCAN_MESSAGE_EXTENDED;
                }
                else
                {
                    txBuf.MSGTYPE = TPCANMessageType.PCAN_MESSAGE_STANDARD;
                }

                ret = PCANBasic.Write(UsbChl, ref txBuf);

            }
            return ret;
        }

        public TPCANStatus GetStatus()
        {
          return  PCANBasic.GetStatus(UsbChl);
        }

        public void Reset()
        {
            PCANBasic.Reset(UsbChl);
            PCANBasic.Uninitialize(UsbChl);
            Thread.Sleep(1000);
        }


    }
}
